﻿
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Minio;
using Minio.ApiEndpoints;
using Minio.DataModel.Args;
using Newtonsoft.Json;
using System.Threading.Tasks;

namespace B.S.BaseData.Read.API.Controllers
{
    /// <summary>
    /// 文件管理
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class FileUploadController : ControllerBase
    {
        private readonly IMinioClient _minioClient;
        private string bucketName = "sheepimages";

        public FileUploadController()
        {
            _minioClient = new MinioClient()
                           .WithEndpoint("10.223.8.8:9000")
                           .WithCredentials("admin", "admin123")
                           .WithSSL(false)
                           .Build();

        }

        /// <summary>
        /// 列出所有的桶
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> ListBuckets()
        {
            var buckets = await _minioClient.ListBucketsAsync().ConfigureAwait(false);
            return Ok(buckets);
        }

        /// <summary>
        /// 上传单个文件
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> UploadFile(IFormFile file)
        {
            //检查桶是否存在
            var beArgs = new BucketExistsArgs().WithBucket(bucketName);
            bool found = await _minioClient.BucketExistsAsync(beArgs);
            //如果桶不存在则创建桶
            if (!found)
            {
                var mbArgs = new MakeBucketArgs().WithBucket(bucketName);
                await _minioClient.MakeBucketAsync(mbArgs).ConfigureAwait(false);
            }

            //获取文件名
            var objectName = file.FileName;

            //使用流数据上传文件
            var putArgs = new PutObjectArgs()
                .WithBucket(bucketName)
                .WithObject(objectName)
                .WithStreamData(file.OpenReadStream())
                .WithContentType(file.ContentType)
                .WithObjectSize(file.Length);
            await _minioClient.PutObjectAsync(putArgs).ConfigureAwait(false);

            var getArgs = new PresignedGetObjectArgs()
                .WithBucket(bucketName)
                .WithObject(objectName)
                .WithExpiry(7200);

            var url = await _minioClient.PresignedGetObjectAsync(getArgs).ConfigureAwait(false);
            return Ok(JsonConvert.SerializeObject(url));
        }


        /// <summary>
        /// 上传多个文件
        /// </summary>
        /// <param name="formFiles"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> UploadFiles(IFormFileCollection formFiles)
        {
            //检查桶是否存在
            var beArgs = new BucketExistsArgs().WithBucket(bucketName);
            bool found = await _minioClient.BucketExistsAsync(beArgs);

            //如果不存在则创建桶
            if (!found)
            {
                var mbArgs = new MakeBucketArgs().WithBucket(bucketName);
                await _minioClient.MakeBucketAsync(mbArgs).ConfigureAwait(false);

            }

            var formFileList = new List<string>();
            foreach (var formFile in formFiles)
            {
                using var stream = formFile.OpenReadStream();
                //获取文件名称
                var objestName = formFile.FileName;
                formFileList.Add(objestName);
                //使用流数据上传文件
                var putArgs = new PutObjectArgs()
                    .WithBucket(bucketName)
                    .WithObject(objestName)
                    .WithStreamData(stream)
                    .WithStreamData(stream)
                    .WithContentType(formFile.ContentType)
                    .WithObjectSize(stream.Length);

                await _minioClient.PutObjectAsync(putArgs).ConfigureAwait(false);

            }
            return Ok(formFileList);
        }

        /// <summary>
        /// 查询sheepimages桶中的文件
        /// </summary>
        /// <returns></returns>
        [HttpGet("list-files")]
        public async Task<IActionResult> ListFiles()
        {
            try
            {
                // 检查存储桶是否存在
                bool found = await _minioClient.BucketExistsAsync(new BucketExistsArgs().WithBucket(bucketName));
                if (!found)
                {
                    return NotFound($"Bucket {bucketName} does not exist");
                }

                // 列出存储桶中的所有对象
                var objects = new List<object>();
                var listArgs = new ListObjectsArgs()
                    .WithBucket(bucketName)
                    .WithRecursive(true);

                var observable = _minioClient.ListObjectsAsync(listArgs);

                var subscription = observable.Subscribe(
                    item => objects.Add(new
                    {
                        Name = item.Key,
                        Size = item.Size,
                        LastModified = item.LastModifiedDateTime,
                        IsDir = item.IsDir
                    }),
                    ex => throw ex,
                    () => { } // 完成回调
                );

                // 等待操作完成（实际应用中可能需要更复杂的处理）
                await Task.Delay(1000); // 简单等待，生产环境应使用更可靠的方式

                return Ok(objects);
            }
            catch (Exception ex)
            {
                return StatusCode(500, $"Internal server error: {ex.Message}");
            }
        }

        [HttpGet]
        public async Task<string> GeneratePreSignedURL()
        {
            // MinIO 配置信息
            string? endpoint = "10.223.8.8:9001"; // 替换为你的 MinIO 服务器地址
            string? accessKey = "P2fMHZRWC0SkD2ZSSd24"; // 替换为你的 Access Key
            string? secretKey = "w557iD6CX8PuLCGFAcoQg60AHq62efYEcHlHpfQc"; // 替换为你的 Secret Key
            bool useSSL = false; // 是否使用 HTTPS

            // 创建 MinIO 客户端
            IMinioClient? minioClient = new MinioClient()
                .WithEndpoint(endpoint)
                .WithCredentials(accessKey, secretKey)
                .WithSSL(useSSL)
                .Build();

            // 存储桶名称和对象名称
            string? bucketName = "xixixi"; // 替换为你的存储桶名称
            string? objectName = "logo.svg"; // 替换为你要上传的文件名

            // 设置预签名 URL 的过期时间（例如：1小时）
            int expires = 1000 * 60 * 24;

            try
            {
                // 生成上传对象的预签名 URL
                //Task<string>? presignedPutUrl = await minioClient.PresignedPutObjectAsync(
                //    bucketName,
                //    objectName,
                //    expires
                //);
                PresignedPutObjectArgs policy = new PresignedPutObjectArgs().WithBucket(bucketName).WithObject(objectName).WithExpiry(expires);

                string? presignedPutUrl = await minioClient.PresignedPutObjectAsync(policy);
                Console.WriteLine("上传预签名 URL: " + presignedPutUrl);
                return presignedPutUrl;
            }
            catch (Exception ex)
            {
                Console.WriteLine("生成预签名 URL 失败: " + ex.Message);
                return ex.Message;
            }
        }
    }
}
